{
 "cells": [
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "## 多层感知机概念：\n",
    "- 多层感知机在输入层和输出层之间增加一个或者多个全连接隐藏层，并通过激活函数转换隐藏层的输出\n",
    "- 常用的激活函数包括ReLU（修正线性单元）、sigmoid、tanh、softmax\n",
    "## １、导入包"
   ],
   "id": "767b4a4bb6c01ef"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-11-11T04:55:00.878521Z",
     "start_time": "2024-11-11T04:55:00.873791Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import torch\n",
    "from torch.utils.data import DataLoader\n",
    "from torchvision import datasets, transforms"
   ],
   "id": "cca70fcd2c7f9fc4",
   "outputs": [],
   "execution_count": 140
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 2、小批量获取数据",
   "id": "5a356ae1598b83a3"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-11-11T04:55:00.992343Z",
     "start_time": "2024-11-11T04:55:00.899791Z"
    }
   },
   "cell_type": "code",
   "source": [
    "mnist_train = datasets.MNIST('../data',transform=transforms.ToTensor(), train=True)\n",
    "mnist_test = datasets.MNIST('../data',transform=transforms.ToTensor(), train=False)\n",
    "train_loader = DataLoader(mnist_train, batch_size=10,shuffle=True)\n",
    "test_loader = DataLoader(mnist_test, batch_size=10,shuffle=True)"
   ],
   "id": "10a83ce40d39faa1",
   "outputs": [],
   "execution_count": 141
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 3、定义模型(多层感知机)\n",
   "id": "436e059116b461c8"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-11-11T04:55:00.999143Z",
     "start_time": "2024-11-11T04:55:00.993995Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# H = XW1 + b1 隐藏层变量\n",
    "# O = HW2 + b2 输出函数\n",
    "net = torch.nn.Sequential(\n",
    "    torch.nn.Flatten(),# 将图像展平为一维向量\n",
    "    torch.nn.Linear(784, 256), # 输入层到隐藏层\n",
    "    torch.nn.ReLU(), # 激活函数\n",
    "    # torch.nn.Linear(256, 64), # 隐藏层到隐藏层\n",
    "    # torch.nn.ReLU(), # 激活函数\n",
    "    torch.nn.Linear(256, 10)) # 输出层"
   ],
   "id": "393d792dc5bfaa2",
   "outputs": [],
   "execution_count": 142
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 4、初始化参数",
   "id": "ee5f8c4ac13a10c9"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-11-11T04:55:01.006376Z",
     "start_time": "2024-11-11T04:55:01.000606Z"
    }
   },
   "cell_type": "code",
   "source": [
    "def init_weights(m):\n",
    "    if type(m) == torch.nn.Linear:\n",
    "        torch.nn.init.normal_(m.weight, std=0.01)\n",
    "net.apply(init_weights)        "
   ],
   "id": "b7380b2b914896dc",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Sequential(\n",
       "  (0): Flatten(start_dim=1, end_dim=-1)\n",
       "  (1): Linear(in_features=784, out_features=256, bias=True)\n",
       "  (2): ReLU()\n",
       "  (3): Linear(in_features=256, out_features=10, bias=True)\n",
       ")"
      ]
     },
     "execution_count": 143,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 143
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 5、定义损失函数",
   "id": "52ab76658eaca030"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-11-11T04:55:01.011239Z",
     "start_time": "2024-11-11T04:55:01.008365Z"
    }
   },
   "cell_type": "code",
   "source": "loss_fn = torch.nn.CrossEntropyLoss(reduction=\"none\") # 交叉熵",
   "id": "9e82f221fece9624",
   "outputs": [],
   "execution_count": 144
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 6、定义优化函数",
   "id": "6854f154234192e1"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-11-11T04:55:01.017381Z",
     "start_time": "2024-11-11T04:55:01.013347Z"
    }
   },
   "cell_type": "code",
   "source": "optimizer = torch.optim.SGD(net.parameters(), lr=0.001) # 学习率不能太小",
   "id": "de963b49f65413d6",
   "outputs": [],
   "execution_count": 145
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 7、训练模型",
   "id": "1e57de4bfeea5629"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-11-11T04:57:13.323006Z",
     "start_time": "2024-11-11T04:55:01.018552Z"
    }
   },
   "cell_type": "code",
   "source": [
    "epochs = 10 # 轮数\n",
    "for epoch in range(epochs):\n",
    "    net.train() # 用于将模型切换到训练模式\n",
    "    for X,y in train_loader:\n",
    "        optimizer.zero_grad()\n",
    "        y_pred = net(X)\n",
    "        loss = loss_fn(y_pred, y) \n",
    "        loss.sum().backward()\n",
    "        optimizer.step()\n",
    "# num_epochs = 10\n",
    "# \n",
    "# for epoch in range(num_epochs):\n",
    "#     model.train()\n",
    "#     running_loss = 0.0\n",
    "#     for images, labels in train_loader:\n",
    "#         optimizer.zero_grad()  # 清零梯度\n",
    "#         outputs = model(images)  # 前向传播\n",
    "#         loss = loss_fn(outputs, labels)  # 计算损失\n",
    "#         loss.backward()  # 反向传播\n",
    "#         optimizer.step()  # 更新权重\n",
    "# \n",
    "#         running_loss += loss.item()\n",
    "# \n",
    "#     print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {running_loss/len(train_loader):.4f}')"
   ],
   "id": "f83b72ac5d82a4f",
   "outputs": [],
   "execution_count": 146
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 9、预测数据",
   "id": "44d8b480119964ee"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-11-11T04:57:13.333163Z",
     "start_time": "2024-11-11T04:57:13.324722Z"
    }
   },
   "cell_type": "code",
   "source": [
    "def get_labels(labels):\n",
    "    text_labels = [\"t-shirt(T恤)\", \"trouser(裤子)\", \"pullover(套衫)\", \"dress(连衣裙)\", \"coat(外套)\", \"sandal(凉鞋)\",\"shirt(衬衫)\", \"sneaker(运动鞋)\",\n",
    "                   \"bag(包)\", \"ankle boot(短靴)\"]\n",
    "    return [text_labels[int(label)] for label in labels ]\n",
    "for X,y in test_loader:\n",
    "    break;\n",
    "trues = get_labels(y)\n",
    "preds = get_labels(net(X).argmax(axis=1))\n",
    "print(trues)\n",
    "print(preds)    "
   ],
   "id": "581efe60b4a2de71",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['pullover(套衫)', 'sandal(凉鞋)', 'shirt(衬衫)', 'sneaker(运动鞋)', 'pullover(套衫)', 'pullover(套衫)', 'dress(连衣裙)', 't-shirt(T恤)', 'ankle boot(短靴)', 'coat(外套)']\n",
      "['pullover(套衫)', 'sandal(凉鞋)', 'shirt(衬衫)', 'sneaker(运动鞋)', 'pullover(套衫)', 'pullover(套衫)', 'dress(连衣裙)', 't-shirt(T恤)', 'ankle boot(短靴)', 'coat(外套)']\n"
     ]
    }
   ],
   "execution_count": 147
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-11-11T04:57:13.336608Z",
     "start_time": "2024-11-11T04:57:13.334377Z"
    }
   },
   "cell_type": "code",
   "source": "",
   "id": "91a6c874907d98fb",
   "outputs": [],
   "execution_count": 147
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
